using namespace boost;
namespace KillerKitty {


	//The regular expression engine
	//handles pattern matching
	class kkRegExEngine : public KillerKittyBase {
	
	public:
		kkRegExEngine();
		~kkRegExEngine();

		//maybe rename to isSigantureMatch, or overload with another func accepting the kkSignature struct? 

		int isMatch(const char* signature,char* bytes, int bytesLength);
		//changed signature const char* -  raga
	private:
		string regFormat(string hex);
	};

	kkRegExEngine::kkRegExEngine() {

	}

	kkRegExEngine::~kkRegExEngine(){
	}

	int kkRegExEngine::isMatch(const char *signature,char* bytes, int bytesLength) {
		regex re;
		string sig;
		
		sig=regFormat(signature);
		try{	
			re.assign(sig);
		}
	
		catch(regex_error& e) {

			log.write(this,"Exception in kkRegExEngine",info);
			return false;
			/*temp error caused due to invalid sig
			  1 Either sig itself is wrong
			  2 or regFormat() screws up 

			  Need a better way of handling this
			*/
		}
		string s(bytes, bytesLength);
		bool match = false;
		try {
			match = regex_match(s, re);
		}
		catch(runtime_error& e) {
			log.write(this,"Exception in kkRegExEngine",info);
			//return -1;
		}

		return match;
		
	}

	string kkRegExEngine::regFormat(string hex) {
		/* regFormat function formats the hex to
		the regular expression syntax of regex
		*/


		/* this regFormat is brute force method
		next update using regex_replace()
		*/
		const string star="(..)*";
		const string byte=".";
		const string nstart=".{";
		const string nend="}";
		const string comma=",";
		const string zero="0";

		for(unsigned int i=0;i<hex.length(); i++) {
			//Replace ?? by .. 
			//in regex . is the place holder for any any char
			if(hex[i]=='?')
				hex.replace(i,1,byte);
			
			//Replace * by (..)*
			// * in hex means any no. of bytes 1 byte=2 hex chars
			if(hex[i]=='*') {
				hex.replace(i,1,star);
				i+=4; 
			}

			if(hex[i]=='{') {
				int j;
				string cond;

				for(j=i;hex[j]!='}';j++);

				cond=hex.substr(i, j-i+1);

				cond[0]='(';
				cond[cond.length()-1]=')';

				for(unsigned k=0; k<cond.length(); k++) {

					if(cond[k]==')' || cond[k]=='|') {
						cond.insert(k,nend);
						k++;
					}

					if(cond[k]=='(' || cond[k]=='|')
					{	
						cond.insert(k+1, nstart);
						k+=2;
						continue;
					}

					if(cond[k]=='-') {
						cond.replace(k,1,comma);
						if(cond[k-1]=='{')
							cond.insert(k++, zero);
					}
				}
				hex.replace(i, (j-i+1), cond);
				i+=cond.length();	
			}
		}
		hex.push_back('*');
		return hex;
	}

};
